#include "freertos/FreeRTOS.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_log.h"
#include "esp_system.h"
#include "string.h"
#include "manager.h"
#include "WifiManager/WiFiManagerDefine.h"

static const char *TAG = "MAIN";

ManageModule *manageModule = NULL;
//--------------wifi_manager的回调函数 Wi-Fi 状态回调函数--------------
void wifi_event_callback(WifiManager *manager, esp_event_base_t event_base, int32_t event_id, NetConnectType netConnectType)
{
    if (event_base == WIFI_EVENT)
    {
        if (event_id == WIFI_EVENT_STA_DISCONNECTED)
        {
            ESP_LOGI(TAG, "连接Wifi失败，重连主设备热点");
            // 如果连接失败，则再次连接到主设备的热点
            WiFiConfig wifiConfig = {0};
            wifiConfig.netConnectType = TYPE_ESP32AP;
            strncpy((char *)wifiConfig.ssid, AP_SSID, sizeof(AP_SSID));
            strncpy((char *)wifiConfig.password, AP_PASS, sizeof(AP_PASS));
            if (xQueueSend(manageModule->wifiConfigQueue, &wifiConfig, portMAX_DELAY) != pdTRUE)
            {
                ESP_LOGE(TAG, "发送 Wi-Fi 配置信息到队列失败");
            }
        }
        return;
    }
    if (event_id != IP_EVENT_STA_GOT_IP)
    {
        return;
    }
    if (netConnectType == TYPE_ESP32AP && manageModule->device_client_task_handle != NULL)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
        vTaskResume(manageModule->device_client_task_handle); // 启动设备任务
    }
    if (netConnectType == TYPE_WIFI)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 提示信息的回调，用作提示音
void tip_event_callback(WifiManager *manager, const char *tip)
{
    ESP_LOGI(TAG, "%s", tip);
}

//-----------------------设备管理任务的回调 如重连wifi-----------------
void net_config_callback(NetConfig netConfig)
{
    ESP_LOGI(TAG, "将要连接WIFI %s", netConfig.wifiConfig.ssid);
    if (xQueueSend(manageModule->wifiConfigQueue, &netConfig.wifiConfig, portMAX_DELAY) != pdTRUE)
    {
        ESP_LOGE(TAG, "发送 Wi-Fi 配置信息到队列失败");
    }
    vTaskDelay(pdMS_TO_TICKS(1000)); // 等待三秒 再发出mqtt连接的队列
    ESP_LOGI(TAG, "将要连接MQTT %s:%d", netConfig.mqttIP, netConfig.mqttPort);
    if (xQueueSend(manageModule->mqttConfigQueue, &netConfig, portMAX_DELAY) != pdTRUE)
    {
        ESP_LOGE(TAG, "发送 MQTT 配置信息到队列失败");
    }
}

// ---------------- mqtt任务的回调 ----------------
//---mqtt--连接
void mqtt_connect_callback(MqttClient *manager, esp_event_base_t event_base, int32_t event_id)
{
}

//---收到发送的数据
void mqtt_recv_msg_callback(MqttClient *manager, MessageType messageType, void *data)
{
    
}
/* 配置wifi的任务 */
void wifi_config_task(void *arg)
{
    // 初始化 Wi-Fi 管理器
    WifiManager *wifiManager = wifi_manager_init(wifi_event_callback, tip_event_callback);
    WiFiConfig wifiConfig = {0};
    wifiConfig.netConnectType = TYPE_ESP32AP;
    strncpy((char *)wifiConfig.ssid, AP_SSID, sizeof(AP_SSID));
    strncpy((char *)wifiConfig.password, AP_PASS, sizeof(AP_PASS));
    if (!wifiManager)
    {
        printf("Wi-Fi 管理器初始化失败！\n");
        return;
    }
    manageModule->wifiManager = wifiManager;
    connectWifiOrAp(wifiManager, &wifiConfig);

    WiFiConfig targetWifiConfig = {0}; // 用于保存从队列接收到的新的 Wi-Fi 配置信息
    while (1)
    {
        // 阻塞等待新的 Wi-Fi 配置信息
        if (xQueueReceive(manageModule->wifiConfigQueue, &targetWifiConfig, portMAX_DELAY) == pdTRUE)
        {
            ESP_LOGI(TAG, "获取到目标 Wi-Fi 配置：SSID=%s, Password=%s", targetWifiConfig.ssid, targetWifiConfig.password);
            wifi_config_t wifiConfig;
            esp_wifi_get_config(WIFI_IF_STA, &wifiConfig); // 获取 Wi-Fi 配置信息
            if (strncmp((char *)wifiConfig.sta.ssid, (char *)targetWifiConfig.ssid, sizeof(wifiConfig.sta.ssid)) != 0)
            {
                ESP_LOGI(TAG, "当前连接 SSID 与新的 SSID 不同，开始重新连接...");
                // 获取互斥量，确保 Wi-Fi 连接操作是单线程执行
                if (xSemaphoreTake(manageModule->wifiConnectMutex, portMAX_DELAY) == pdTRUE)
                {
                    // 调用 connectWifiOrAp 执行新的连接
                    connectWifiOrAp(wifiManager, &targetWifiConfig);
                    int retryCount = 0; // 等待 Wi-Fi 连接成功
                    while (retryCount < MAX_RETRY_CONNECT_NET)
                    {
                        wifi_ap_record_t ap_info;
                        esp_wifi_sta_get_ap_info(&ap_info); // 获取当前连接的 AP 信息
                        if (ap_info.ssid[0] != 0)           // 判断 AP SSID 是否为空
                        {
                            ESP_LOGI(TAG, "成功连接到目标 Wi-Fi");
                            break; // 成功连接后退出循环
                        }
                        retryCount++;
                        vTaskDelay(pdMS_TO_TICKS(5000)); // 等待 5 秒再重新查询
                    }
                    xSemaphoreGive(manageModule->wifiConnectMutex); // 释放互斥量
                    if (retryCount == MAX_RETRY_CONNECT_NET)
                    {
                        ESP_LOGE(TAG, "连接目标 Wi-Fi 失败，退出任务");
                        continue; // 如果连接失败，退出任务或者其他处理
                    }
                }
            }
            else
            {
                ESP_LOGI(TAG, "当前已连接到目标 Wi-Fi，不需要重新连接");
            }
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

/* Mqtt连接任务 */
void mqtt_task(void *arg)
{
    MqttClient *mqtt_client = mqtt_client_init(mqtt_connect_callback, mqtt_recv_msg_callback);
    if (!mqtt_client)
    {
        ESP_LOGE(TAG, "Failed to create MqttClient");
        return;
    }
    manageModule->mqttClient = mqtt_client;
    ESP_LOGI(TAG, "mqtt_client Initialized and ready.");

    NetConfig targetNetConfig = {0}; // 用于保存从队列接收到的新的 Wi-Fi 配置信息
    while (1)
    {
        // 阻塞等待新的 Wi-Fi 配置信息
        if (xQueueReceive(manageModule->mqttConfigQueue, &targetNetConfig, portMAX_DELAY) == pdTRUE)
        {
            MqttClient *mqttClient = manageModule->mqttClient;
            if (!mqttClient)
            {
                continue;
            }
            // 如果当前已经连接到相同的服务器，直接返回
            if (!mqtt_connect_if_needed(mqttClient, targetNetConfig.mqttIP, targetNetConfig.mqttPort))
            {
                ESP_LOGI(TAG, "已经连接到相同的 MQTT 服务器，无需重连");
                continue;
            }

            // 获取互斥量，保护 MQTT 配置重连操作
            if (xSemaphoreTake(manageModule->mqttConnectMutex, portMAX_DELAY) == pdTRUE)
            {
                mqtt_client_start(manageModule->mqttClient, targetNetConfig.mqttIP, NULL, NULL, targetNetConfig.mqttPort, targetNetConfig.mqttSubTopic);
                xSemaphoreGive(manageModule->mqttConnectMutex); // 释放互斥量
            }
            else
            {
                ESP_LOGE(TAG, "无法获取互斥量，跳过 MQTT 重连");
            }
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

/* 设备管理任务 */
void devicemanager_task(void *arg)
{
    DeviceManagerClient *deviceManagerClient = manager_init();
    if (!deviceManagerClient)
    {
        ESP_LOGE(TAG, "Failed to create ESPNowManager");
        return;
    }
    manageModule->deviceManagerClient = deviceManagerClient;
    ESP_LOGI(TAG, "ESP-NOW Initialized and ready.");
    DeviceManagerClient_set_recv_netConfig_callback(deviceManagerClient, net_config_callback);
    vTaskSuspend(NULL);
}

void app_main(void)
{
    // 为 manageModule 分配内存
    manageModule = (ManageModule *)calloc(1, sizeof(ManageModule));
    if (!manageModule)
        return;

    // 创建 Wi-Fi 配置信息队列
    manageModule->wifiConfigQueue = xQueueCreate(10, sizeof(WiFiConfig)); // 可以容纳多个配置
    if (manageModule->wifiConfigQueue == NULL)
    {
        ESP_LOGE(TAG, "创建 Wi-Fi 配置信息队列失败");
        return;
    }
    // 创建互斥量，用于同步 Wi-Fi 连接操作
    manageModule->wifiConnectMutex = xSemaphoreCreateMutex();
    if (manageModule->wifiConnectMutex == NULL)
    {
        ESP_LOGE(TAG, "创建 Wi-Fi 连接互斥量失败");
        return;
    }

    // 创建 MQTT 配置信息队列
    manageModule->mqttConfigQueue = xQueueCreate(10, sizeof(NetConfig)); // 可以容纳多个配置
    if (manageModule->mqttConfigQueue == NULL)
    {
        ESP_LOGE(TAG, "创建 MQTT 配置信息队列失败");
        return;
    }

    // 创建互斥量，用于同步 MQTT 连接操作
    manageModule->mqttConnectMutex = xSemaphoreCreateMutex();
    if (manageModule->mqttConnectMutex == NULL)
    {
        ESP_LOGE(TAG, "创建 MQTT 连接互斥量失败");
        return;
    }

    // 创建任务执行 配置wifi
    xTaskCreatePinnedToCore(wifi_config_task, "wifi_config_task", 1024 * 8, NULL, 2, &manageModule->wifi_config_task_handle, 0);

    // 创建任务执行 Mqtt 等待设备连上wifi
    xTaskCreatePinnedToCore(mqtt_task, "mqtt_task", 1024 * 8, NULL, 2, &manageModule->mqtt_task_handle, 1);

    // 创建任务执行 设备管理 等待连上主设备的热点
    xTaskCreatePinnedToCore(devicemanager_task, "devicemanager_task", 16384, NULL, 2, &manageModule->device_client_task_handle, 1);
    vTaskSuspend(manageModule->device_client_task_handle);
}
